//==============================================================================
// MerOverlapper.hh
//
// ----------------------------------------------------------------------------
// $Id: //CBT-depot/CompBioToolsApps/atlas-overlapper/MerOverlapper.hh#4 $
//------------------------------------------------------------------------------
// $Log: $
//
//==============================================================================
//.......1.........2.........3.........4.........5.........6.........7.........8


#ifndef _MER_OVERLAPPER
#define _MER_OVERLAPPER

#include "LocalSTL.hh"
#include "Sequence.hh"
#include "Sequence3Bit.hh"
#include "MerHashMap.hh"


#define MAX_SEQ_LENGTH 500000
#define MAX_BAND_SIZE  25

#define mGapScore -2
#define mMatchScore 1
#define mMisMatchScore -1


class OverlapInfo{
public:
  int  mSpan;  // Region of overlap, in bp
  int  mScore;
  int  mLeftExtension;
  int  mRightExtension;
  char mSense;
  int  mCopyNum;
};

class ReadOverlaps: public hash_map<int,OverlapInfo,hash<int>,equal_to<int> >{
public:

};


class MerOverlapper{
public:

  int  mKillCount;
  int  mSamplesPerRead;
  int  mSampleGap;
  int  mMinReadSize;  // Skips reads shorter than this. 
  bool mInteriorSampling;
  bool mOriginRelative;
  bool mFlipDirection;

  int    mMaxSeed;  

  double mStDevRepeatCutoff;
  int    mRepeatCutoff;
  int    mMaxMismatchPercent;

  bool   mMultipleEdgeValues;
  bool   mReportSeqLength;


	// Previously, the location was hard-coded to be efficient for 
	// read overlaps.  
  //MerHashMap mSourceHash;

	// Now, there are two MerLocation classes to choose from...
	// BigMerLocation, which gives a whole integer for the base index, 
	// and MerLocation, which only gives 12 bits for the base idx.  
	MerHashMap<MerHashF,MerLocation> mSourceHash;

  //MerSet  mRepeatMers;
  SimpleMerHash mRepeatMers;

  void ReadRepeatMers(istream &fin,int minCount);

  int mBandSize;
  // int gMOScoreTable[MAX_ALIGN_SIZE][MAX_ALIGN_SIZE];

  void SetBandSize(int bandSize){
	 mBandSize = bandSize;
	 InitGapPenalties(bandSize);
  }

  void InitGapPenalties(int band);

    
  //MerOverlapper(MerHashMap &SourceHash){
	 //mpSourceHash = &SourceHash;
  //	 mSamplesPerRead = 8;
  //	 mSampleGap = 5;
  //	 mMultipleEdgeValues = false;
  // mMinReadSize = 100;

	 //mBandSize = 2;
	 //InitGapPenalties(mBandSize);
  
	 // One-time initialization of edge gap penalties. 
	 //	 int i,j;
	 //for(i = 0;i<MAX_ALIGN_SIZE;i++)
	 //		gMOScoreTable[i][0] = i*mGapScore;
	 //for(j = 0;j<MAX_ALIGN_SIZE;j++)
	 //		gMOScoreTable[0][j]=j*mGapScore;

  //};

  MerOverlapper(){
	 mKillCount = 0;
	 mSamplesPerRead = 8;
	 mSampleGap = 5;
	 mMinReadSize = 100;
	 mInteriorSampling = false;
	 mMultipleEdgeValues = false;	 

	 mRepeatMers.SetMerSize(Mer::mMerSize);

	 //mBandSize = 2;

	 //InitGapPenalties(mBandSize);

	 // One-time initialization of edge gap penalties. 
	 //int i,j;
	 //for(i = 0;i<MAX_ALIGN_SIZE;i++)
	 //		gMOScoreTable[i][0] = i*mGapScore;
	 //for(j = 0;j<MAX_ALIGN_SIZE;j++)
	 //		gMOScoreTable[0][j]=j*mGapScore;
	 
  };


  void AddToHashMap(Sequence3Bit &Seq,int SeqIdx);

  void GetNextRead0(istream &qin,Sequence &Read,string &nextDesc);

  bool GetNextRead(istream &inFile,Sequence &Read,char *buffer,int bufSize);

  void ComputeAllOverlaps(istream &qin,ostream &fout);
  void FindOverlapsWithSource(Sequence3Bit &QueryRead,ostream &fout);

  void SearchSamplesAgainstHash(Sequence3Bit &QueryRead,
										  MerSearchResultVec<MerLocation> &FwdHits,
										  MerSearchResultVec<MerLocation> &RevHits);

  void SearchEndSamplesAgainstHash(Sequence3Bit &QueryRead,
										  MerSearchResultVec<MerLocation> &FwdHits,
										  MerSearchResultVec<MerLocation> &RevHits);

  void EvaluateHits(MerSearchResultVec<MerLocation> &Results,ReadOverlaps &Overlaps);


  void HandleFwdCase1(int& a,int& b,int &i,int &iplus,
							 Sequence3Bit &Source,Sequence3Bit &Query,int &totalscore,MerSearchResultVec<MerLocation> &Results);

  void HandleFwdCase2(int&,int&,int &i,int &iplus,
							 Sequence3Bit &Source,Sequence3Bit &Query,int &totalscore,MerSearchResultVec<MerLocation> &Results);
  void HandleFwdCase3(int&,int&,int &i,int &iplus,Sequence3Bit &Source,Sequence3Bit &Query,int &totalscore){}

  void HandleRevCase1(int &i,int &iplus,Sequence3Bit &Source,Sequence3Bit &Query,int &totalscore);
  void HandleRevCase2(int &i,int &iplus,Sequence3Bit &Source,Sequence3Bit &Query,int &totalscore);
  void HandleRevCase3(int &i,int &iplus,Sequence3Bit &Source,Sequence3Bit &Query,int &totalscore);


  void EvaluateFwdHits(MerSearchResultVec<MerLocation> &Results,ReadOverlaps &Overlaps);
  void EvaluateRevHits(MerSearchResultVec<MerLocation> &Results,ReadOverlaps &Overlaps);

  void EvaluateFwdHits(MerSearchResultVec<MerLocation> &Results,ReadOverlaps &Overlaps,Sequence3Bit &QueryRead);
  void EvaluateRevHits(MerSearchResultVec<MerLocation> &Results,ReadOverlaps &Overlaps,Sequence3Bit &QueryRead);

  //  void EvaluateFwdHits(MerSearchResultVec<MerLocation> &Results,Sequence3Bit &QueryRead,
  //						  ReadOverlaps &Overlaps);

  //  void EvaluateRevHits(MerSearchResultVec<MerLocation> &Results,Sequence3Bit &QueryRead,
  //						ReadOverlaps &Overlaps);

  void SaveOverlaps(ostream &fout,string &ReadName,int ReadSize,ReadOverlaps &Overlaps);

  void ComputeGlobalAlignmentScore(Sequence3Bit &Query,int QStart,int QEnd,
											  Sequence3Bit &Source,int SStart,int SEnd,int &score);

  void ComputeBandedAlignmentScore(Sequence3Bit &Query,int QStart,int QEnd, 
											  Sequence3Bit &Source,int SStart,int SEnd, int band, int &score);

  void Bug2();

};


#endif
